package com.bcx.wind.workflow.imp.cmd.managercmd;

import com.bcx.wind.workflow.access.QueryFilter;
import com.bcx.wind.workflow.core.constant.TaskLevel;
import com.bcx.wind.workflow.core.constant.TaskStatus;
import com.bcx.wind.workflow.core.constant.TaskType;
import com.bcx.wind.workflow.core.constant.WorkflowOperate;
import com.bcx.wind.workflow.entity.WindActHistory;
import com.bcx.wind.workflow.entity.WindOrder;
import com.bcx.wind.workflow.entity.WindTask;
import com.bcx.wind.workflow.entity.WindTaskActor;
import com.bcx.wind.workflow.errorcontext.WindError;
import com.bcx.wind.workflow.interceptor.Command;
import com.bcx.wind.workflow.interceptor.CommandContext;
import com.bcx.wind.workflow.pojo.WindUser;
import com.bcx.wind.workflow.support.Assert;
import com.bcx.wind.workflow.support.JsonHelper;
import com.bcx.wind.workflow.support.ObjectHelper;
import com.bcx.wind.workflow.support.TimeHelper;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bcx.wind.workflow.core.constant.OrderVariableConstant.JOINTLY_MIN_COUNT;
import static com.bcx.wind.workflow.core.constant.OrderVariableConstant.JOINTLY_NOW_COUNT;
import static com.bcx.wind.workflow.core.constant.OrderVariableConstant.JOINTLY_SUCCESS_COUNT;
import static com.bcx.wind.workflow.message.ErrorCode.*;

/**
 * 去除指定任务的指定审批人命令
 *
 * @author zhanglei
 */
public class ReduceApproveUserCommand implements Command<WindTask> {

    /**
     * 任务ID
     */
    private final String taskId;

    /**
     * 审批人
     */
    private final List<String> approveUsers;

    /**
     * 当前操作人
     */
    private final  WindUser user;

    /**
     * 执行数据
     */
    private CommandContext commandContext;

    /**
     * 操作的任务
     */
    private WindTask windTask;

    /**
     * 操作任务的审批人ID集合
     */
    private List<String> taskActors;

    /**
     * 当前流程实例下所有的任务实例
     */
    private List<WindTask>  windTasks;


    /**
     * 当前流程实例
     */
    private WindOrder windOrder;


    /**
     * 去除审批人是否包含当前任务的所有审批人
     */
    private boolean ordinaryAllActor;


    public ReduceApproveUserCommand(String taskId,List<String> approveUsers,WindUser windUser){
        this.taskId = taskId;
        this.approveUsers = approveUsers;
        this.user = windUser;
    }

    @Override
    public WindTask executor(CommandContext context) {
        try{
            this.commandContext = context;
            return execute();
        }catch (Exception e) {
            return null;
        }
    }

    private WindTask execute() {
        //校验参数
        checkArgs();
        //执行
        if(TaskLevel.child.name().equals(this.windTask.getTaskLevel())){
            this.commandContext.access().removeTaskInstanceById(this.taskId);
            this.commandContext.access().removeTaskActorByTaskId(this.taskId);
            changeTaskHistory();
        }else if(TaskLevel.main.name().equals(this.windTask.getTaskLevel())){

            String taskType = this.windTask.getTaskType();
            //普通任务
            if (TaskType.ordinary.name().equals(taskType)) {
                Assert.isTrueError(TASK_IS_ONLY,this.windTasks.size() == 1 && this.taskActors.size() == 1);
                Assert.isTrueError(TASK_IS_ONLY,windTasks.size() == 1 && this.ordinaryAllActor);
                for(String actor : this.approveUsers){
                    this.commandContext.access().removeTaskActor(this.taskId,actor);
                }
            }
            //会签
            else if(TaskType.jointly.name().equals(taskType)){
                Assert.isTrueError(TASK_IS_ONLY,this.windTasks.size() == 1 && this.taskActors.size() == 1);
                Assert.isTrueError(TASK_IS_ONLY,windTasks.size() == 1 && this.ordinaryAllActor);
                this.commandContext.access().removeTaskInstanceById(this.taskId);
                this.commandContext.access().removeTaskActorByTaskId(this.taskId);
                //更新历史履历
                changeTaskHistory();
                //更新流程实例
                changeOrderVariableForJointly();
            }else{
                WindError.error(TASK_NOT_SUPPORT_OPERATE,null);
            }
        }else{
            WindError.error(TASK_NOT_SUPPORT_OPERATE,null);
        }

        return this.windTask;
    }


    /**
     * 会签类型加签更新流程实例变量数据
     *
     */
    private void changeOrderVariableForJointly(){
        if(this.windOrder != null){

            Map<String,Object> variable = windOrder.variable();
            Object jointlyMinCount = variable.get(JOINTLY_MIN_COUNT);
            if(!ObjectHelper.isEmpty(jointlyMinCount)){
                Map<String,Object> map = JsonHelper.objectToMap(jointlyMinCount);

                if(!ObjectHelper.isEmpty(map)){
                    Object approveUserCount = map.get(windTask.getTaskName());

                    if (!ObjectHelper.isEmpty(approveUserCount)) {
                        Map<String,Object> approveUserCountMap = JsonHelper.objectToMap(approveUserCount);

                        if(!ObjectHelper.isEmpty(approveUserCountMap)){
                            Object successCount = approveUserCountMap.get(JOINTLY_SUCCESS_COUNT);
                            Object nowCount = approveUserCountMap.get(JOINTLY_NOW_COUNT);
                            if(!ObjectHelper.hasEmpty(successCount,nowCount)){
                                int success = Integer.parseInt(successCount.toString());
                                int now = Integer.parseInt(nowCount.toString());
                                //校验是否可以关闭
                                Assert.isTrueError(TASK_IS_ONLY,success - now <=1);
                                approveUserCountMap.put(JOINTLY_SUCCESS_COUNT,Integer.toString(success - 1));
                                map.put(windTask.getTaskName(),approveUserCountMap);
                                variable.put(JOINTLY_MIN_COUNT,map);
                                this.windOrder.setVariable(JsonHelper.toJson(variable));
                                this.commandContext.access().updateOrderInstance(this.windOrder);
                            }
                        }
                    }

                }
            }

        }
    }



    /**
     * 更新子任务历史
     */
    private void changeTaskHistory(){
        QueryFilter filter = new QueryFilter()
                .setTaskId(this.taskId);
        List<WindActHistory> actHistories = this.commandContext.access().selectActiveHistoryList(filter);
        if(!ObjectHelper.isEmpty(actHistories)){
            WindActHistory actHistory = actHistories.get(0);
            actHistory.setOperate(WorkflowOperate.close.name())
                    .setSubmitUserVariable(JsonHelper.toJson(user()))
                    .setActorId(user().proxyUserId())
                    .setActorName(user().proxyUserName())
                    .setApproveTime(TimeHelper.nowDate());
            this.commandContext.access().updateActiveHistory(actHistory);
        }
    }


    private void checkArgs(){
        Assert.notEmptyError(TASK_ID_IS_NULL,this.taskId);
        QueryFilter filter = new QueryFilter()
                .setTaskId(this.taskId)
                .setStatus(TaskStatus.run.name());
        List<WindTask> tasks = this.commandContext.access().selectTaskInstanceList(filter);
        Assert.notEmptyError(TASK_ID_IS_NULL,tasks);
        this.windTask = tasks.get(0);

        //所有任务实例
        QueryFilter orderFilter = new QueryFilter()
                .setOrderId(this.windTask.getOrderId());
        this.windTasks = this.commandContext.access().selectTaskInstanceList(orderFilter);

        //流程实例
        this.windOrder = this.commandContext.access().getOrderInstanceById(this.windTask.getOrderId());
        Assert.notEmptyError(DATABASE_OPERATE_ERROR,windOrder);

        //审批人
        QueryFilter actorFilter = new QueryFilter()
                .setTaskId(this.taskId);
        List<WindTaskActor> actors = this.commandContext.access().selectTaskActorList(actorFilter);
        Assert.notEmptyError(TASK_NOT_SUPPORT_OPERATE,actors);
        this.taskActors = actors.stream().map(WindTaskActor::getActorId).collect(Collectors.toList());

        //校验去除审批人是否存在
        Assert.notEmptyError(TASK_OPERATOR_IS_NULL,this.approveUsers);
        for(String actor : this.approveUsers){
            Assert.isTrueError(APPROVE_USER_NOT_EXIST,!this.taskActors.contains(actor),actor);
        }

        //是否包含任务的所有审批人
        this.ordinaryAllActor = this.approveUsers.size() == this.taskActors.size();
    }


    private WindUser user(){
        return this.user == null ? new WindUser()
                .setUserId("admin")
                .setUserName("管理员") : this.user;
    }

}























